<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="pQRDI" id="pQRDI"><span data-lake-id="u37297fcf" id="u37297fcf">典型回答</span></h1>
  <p data-lake-id="u9b0ec337" id="u9b0ec337"><span data-lake-id="u14053015" id="u14053015">CAP理论：一个分布式系统最多只能同时满足一致性（Consistency）、可用性（Availability）和分区容错性（Partition tolerance）这三项中的两项。</span></p>
  <p data-lake-id="u8273f058" id="u8273f058"><span data-lake-id="ud3241f16" id="ud3241f16" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u4b9f79f6" id="u4b9f79f6" style="text-align: center"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1696935889555-7b34a3f5-e5d8-496e-b7a5-cea10aa6a113.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ue6d7d2fc" id="ue6d7d2fc"><br></p>
  <p data-lake-id="u6c13a131" id="u6c13a131"><span data-lake-id="u4fc39589" id="u4fc39589">网上有很多关于CAP的介绍，其中关于一致性、可用性及分区容错性的介绍也有很多，但是这里需要重新纠正一下CAP中这三个特性的意思（</span><a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" data-lake-id="ue3c8b4ae" id="ue3c8b4ae"><span data-lake-id="ue8a40aa0" id="ue8a40aa0">https://en.wikipedia.org/wiki/CAP_theorem</span></a><span data-lake-id="u7f010256" id="u7f010256"> ）：</span></p>
  <p data-lake-id="u7aed0bce" id="u7aed0bce"><span data-lake-id="u7fd4f50e" id="u7fd4f50e">​</span><br></p>
  <ul list="u2e8d1944">
   <li fid="u7c5d7b1c" data-lake-id="uce995983" id="uce995983"><span data-lake-id="u3e1d745f" id="u3e1d745f">一致性 </span></li>
  </ul>
  <ul list="u2e8d1944" data-lake-indent="1">
   <li fid="u7c5d7b1c" data-lake-id="ua2b3f644" id="ua2b3f644"><span data-lake-id="u25271793" id="u25271793">每次读取都会收到最新的写入数据或错误信息。</span></li>
  </ul>
  <ul list="u2e8d1944" start="2">
   <li fid="u7c5d7b1c" data-lake-id="uecfb60c2" id="uecfb60c2"><span data-lake-id="u1ed60689" id="u1ed60689">可用性 </span></li>
  </ul>
  <ul list="u2e8d1944" data-lake-indent="1">
   <li fid="u7c5d7b1c" data-lake-id="u51497add" id="u51497add"><span data-lake-id="uea6af882" id="uea6af882">每个请求都会收到（非错误的）响应，但不能保证响应包含最新的写入数据。</span></li>
  </ul>
  <ul list="u2e8d1944" start="3">
   <li fid="u7c5d7b1c" data-lake-id="u485eb275" id="u485eb275"><span data-lake-id="u93231b47" id="u93231b47">分区容忍性 </span></li>
  </ul>
  <ul list="u2e8d1944" data-lake-indent="1">
   <li fid="u7c5d7b1c" data-lake-id="u9e9d4b23" id="u9e9d4b23"><span data-lake-id="uc50cbc1d" id="uc50cbc1d">尽管网络节点之间会丢弃（或延迟）任意数量的消息，系统仍然能够继续运行。</span></li>
  </ul>
  <p data-lake-id="u1c091298" id="u1c091298"><span data-lake-id="u2050e7fe" id="u2050e7fe">​</span><br></p>
  <p data-lake-id="u35f5e9af" id="u35f5e9af"><span data-lake-id="u3accb792" id="u3accb792">注意，可用性和分区容错性很多人都不会理解错误，但是一致性可能和大家认为的不太一样（甚至和网上99%讲CAP的文章都不一样）。</span></p>
  <p data-lake-id="ua17d69aa" id="ua17d69aa"><br></p>
  <p data-lake-id="u8197b5c4" id="u8197b5c4"><span data-lake-id="u2817621b" id="u2817621b">这里面的一致性，其实指的是强一致性，但是强一致性也并不是大家普遍认为的："all nodes see the same data at the same time"，这只是其中一种情况，或者说是一种强一致性模型。</span></p>
  <h1 data-lake-id="UUVc6" id="UUVc6"><span data-lake-id="uc039dc26" id="uc039dc26">扩展知识</span></h1>
  <h2 data-lake-id="Zz06R" id="Zz06R"><span data-lake-id="u90d8b254" id="u90d8b254">一致性模型</span></h2>
  <p data-lake-id="uda324299" id="uda324299"><br></p>
  <p data-lake-id="u920a99af" id="u920a99af" style="text-align: justify"><span data-lake-id="u31a96ece" id="u31a96ece" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u37493e64" id="u37493e64" style="text-align: justify"><span data-lake-id="ud975b3d6" id="ud975b3d6" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">在上文中，我们介绍过一致性模型中的强一致性其实有多种，包括了线性一致性、顺序一致性等，不同的分布式系统中，采取的强一致性模型并不一致，但是只要是其中的一种模型的实现，我们就可以认为这个系统是保证了一致性的。</span></p>
  <p data-lake-id="uc2be1e51" id="uc2be1e51" style="text-align: justify"><span data-lake-id="u57ff031e" id="u57ff031e" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u63848051" id="u63848051" style="text-align: justify"><span data-lake-id="u58fdc442" id="u58fdc442" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">如，Zookeeper保证的就是强一致模型中的顺序一致性而不是线性一致性。</span></p>
  <p data-lake-id="u11462b4d" id="u11462b4d" style="text-align: justify"><span data-lake-id="u84a3fd02" id="u84a3fd02" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="uefb2adc6" id="uefb2adc6" style="text-align: justify"><span data-lake-id="u7140d365" id="u7140d365" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <h3 data-lake-id="egQv2" id="egQv2" style="text-align: justify"><span data-lake-id="u8da15c46" id="u8da15c46" style="color: rgb(85, 85, 85)">Availability 可用性</span></h3>
  <p data-lake-id="ue703d350" id="ue703d350"><br></p>
  <p data-lake-id="uca2e4505" id="uca2e4505" style="text-align: justify"><span data-lake-id="u6a46734f" id="u6a46734f">可用性指“Reads and writes always succeed”，即</span><span data-lake-id="u18fa7cb0" id="u18fa7cb0" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">服务一直可用，而且是正常响应时间。</span></p>
  <p data-lake-id="ud67cc48a" id="ud67cc48a" style="text-align: justify"><span data-lake-id="u54bfe1c9" id="u54bfe1c9" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u418079b3" id="u418079b3" style="text-align: justify"><span data-lake-id="u87d2ac78" id="u87d2ac78" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">对于一个可用性的分布式系统，每一个非故障的节点必须对每一个请求作出响应。所以，一般我们在衡量一个系统的可用性的时候，都是通过停机时间来计算的。</span></p>
  <p data-lake-id="ue3689e89" id="ue3689e89" style="text-align: justify"><span data-lake-id="u9f1663dc" id="u9f1663dc" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <table data-lake-id="JlEYq" id="JlEYq" margin="true" class="lake-table" style="width: 750px">
   <colgroup>
    <col width="250">
    <col width="250">
    <col width="250">
   </colgroup>
   <tbody>
    <tr data-lake-id="u9e392722" id="u9e392722">
     <td data-lake-id="u046f9c20" id="u046f9c20" style="background-color: rgb(249, 249, 249)">
      <p data-lake-id="u21bb1d4e" id="u21bb1d4e" style="text-align: center"><span data-lake-id="u50ef6918" id="u50ef6918" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">可用性分类</span></p></td>
     <td data-lake-id="uf1e13e93" id="uf1e13e93" style="background-color: rgb(249, 249, 249)">
      <p data-lake-id="u0010101c" id="u0010101c" style="text-align: center"><span data-lake-id="u1600f610" id="u1600f610" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">可用水平（%）</span></p></td>
     <td data-lake-id="ufe457b8b" id="ufe457b8b" style="background-color: rgb(249, 249, 249)">
      <p data-lake-id="u828f9c35" id="u828f9c35" style="text-align: center"><span data-lake-id="u19d078cc" id="u19d078cc" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">年可容忍停机时间</span></p></td>
    </tr>
    <tr data-lake-id="ue5230df3" id="ue5230df3">
     <td data-lake-id="ua1c1228f" id="ua1c1228f">
      <p data-lake-id="uf74459a1" id="uf74459a1" style="text-align: justify"><span data-lake-id="u8d0fab27" id="u8d0fab27" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">容错可用性</span></p></td>
     <td data-lake-id="u781d3b65" id="u781d3b65">
      <p data-lake-id="u30ef3667" id="u30ef3667" style="text-align: justify"><span data-lake-id="ub6f24b7f" id="ub6f24b7f" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">99.9999</span></p></td>
     <td data-lake-id="uab260be9" id="uab260be9">
      <p data-lake-id="uaa201c36" id="uaa201c36" style="text-align: justify"><span data-lake-id="u94bc49d2" id="u94bc49d2" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">&lt;1 min</span></p></td>
    </tr>
    <tr data-lake-id="ua015609a" id="ua015609a">
     <td data-lake-id="ufbb45553" id="ufbb45553">
      <p data-lake-id="ubdd6b882" id="ubdd6b882" style="text-align: justify"><span data-lake-id="uad7a3067" id="uad7a3067" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">极高可用性</span></p></td>
     <td data-lake-id="uca463b3c" id="uca463b3c">
      <p data-lake-id="uc052c39e" id="uc052c39e" style="text-align: justify"><span data-lake-id="u903dc016" id="u903dc016" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">99.999</span></p></td>
     <td data-lake-id="u131cde26" id="u131cde26">
      <p data-lake-id="ubb0bf1a7" id="ubb0bf1a7" style="text-align: justify"><span data-lake-id="uebce4574" id="uebce4574" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">&lt;5 min</span></p></td>
    </tr>
    <tr data-lake-id="ud90e2759" id="ud90e2759">
     <td data-lake-id="u93a98f11" id="u93a98f11">
      <p data-lake-id="u43f5e509" id="u43f5e509" style="text-align: justify"><span data-lake-id="ua47b286e" id="ua47b286e" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">具有故障自动恢复能力的可用性</span></p></td>
     <td data-lake-id="u0837d83f" id="u0837d83f">
      <p data-lake-id="uc7e28281" id="uc7e28281" style="text-align: justify"><span data-lake-id="u5ce99ada" id="u5ce99ada" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">99.99</span></p></td>
     <td data-lake-id="u6afe5772" id="u6afe5772">
      <p data-lake-id="ueac34c1d" id="ueac34c1d" style="text-align: justify"><span data-lake-id="u6395d318" id="u6395d318" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">&lt;53 min</span></p></td>
    </tr>
    <tr data-lake-id="u063df549" id="u063df549">
     <td data-lake-id="u5fadf6f8" id="u5fadf6f8">
      <p data-lake-id="u87a4b4ce" id="u87a4b4ce" style="text-align: justify"><span data-lake-id="u3009ce5d" id="u3009ce5d" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">高可用性</span></p></td>
     <td data-lake-id="uf76a14d7" id="uf76a14d7">
      <p data-lake-id="ue00e7877" id="ue00e7877" style="text-align: justify"><span data-lake-id="u8039ae56" id="u8039ae56" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">99.9</span></p></td>
     <td data-lake-id="u3e51ad82" id="u3e51ad82">
      <p data-lake-id="u183f2e4e" id="u183f2e4e" style="text-align: justify"><span data-lake-id="u3b5fcc07" id="u3b5fcc07" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">&lt;8.8h</span></p></td>
    </tr>
    <tr data-lake-id="ud57e917b" id="ud57e917b">
     <td data-lake-id="ub0ddf9ac" id="ub0ddf9ac">
      <p data-lake-id="ud84037ae" id="ud84037ae" style="text-align: justify"><span data-lake-id="ue2cc8681" id="ue2cc8681" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">商品可用性</span></p></td>
     <td data-lake-id="ua20202c6" id="ua20202c6">
      <p data-lake-id="u8458dfcc" id="u8458dfcc" style="text-align: justify"><span data-lake-id="ua337d457" id="ua337d457" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">99</span></p></td>
     <td data-lake-id="u2e239c61" id="u2e239c61">
      <p data-lake-id="u9ee796ca" id="u9ee796ca" style="text-align: justify"><span data-lake-id="u330fcf38" id="u330fcf38" class="lake-fontsize-9" style="color: rgb(85, 85, 85)">&lt;3.65 d</span></p></td>
    </tr>
   </tbody>
  </table>
  <p data-lake-id="u136b20d6" id="u136b20d6" style="text-align: justify"><span data-lake-id="udaaa0c07" id="udaaa0c07" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="uc6c7262d" id="uc6c7262d"><span data-lake-id="u697c578a" id="u697c578a">通常我们描述一个系统的可用性时，我们说淘宝的系统可用性可以达到5个9，意思就是说他的可用水平是99.999%，即全年停机时间不超过 (1-0.99999)*365*24*60 = 5.256 min，这是一个极高的要求。</span></p>
  <p data-lake-id="u90320a21" id="u90320a21"><span data-lake-id="u4eb8abea" id="u4eb8abea">​</span><br></p>
  <p data-lake-id="u9f6f64ab" id="u9f6f64ab"><span data-lake-id="u5c1efe94" id="u5c1efe94">好的可用性主要是指系统能够很好的为用户服务，不出现用户操作失败或者访问超时等用户体验不好的情况。一个分布式系统，上下游设计很多系统如负载均衡、WEB服务器、应用代码、数据库服务器等，任何一个节点的不稳定都可以影响可用性。</span></p>
  <p data-lake-id="udb4fb443" id="udb4fb443"><span data-lake-id="u0c393f1b" id="u0c393f1b">​</span><br></p>
  <h3 data-lake-id="kwZ8I" id="kwZ8I" style="text-align: justify"><span data-lake-id="uf556aa76" id="uf556aa76" style="color: rgb(85, 85, 85)">Partition Tolerance分区容错性</span></h3>
  <p data-lake-id="uf81a8624" id="uf81a8624"><br></p>
  <p data-lake-id="u61b23a3d" id="u61b23a3d"><span data-lake-id="uac358b14" id="uac358b14">分区容错性指“the system continues to operate despite arbitrary message loss or failure of part of the system”，即分布式系统在遇到某节点或网络分区故障的时候，仍然能够对外提供满足一致性和可用性的服务。</span></p>
  <p data-lake-id="u271b4dbd" id="u271b4dbd"><span data-lake-id="u03219192" id="u03219192">​</span><br></p>
  <p data-lake-id="u6e3d91af" id="u6e3d91af"><span data-lake-id="uab22924c" id="uab22924c">分区容错性和扩展性紧密相关。在分布式应用中，可能因为一些分布式的原因导致系统无法正常运转。好的分区容错性要求能够使应用虽然是一个分布式系统，而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了，其他剩下的机器还能够正常运转满足系统需求，或者是机器之间有网络异常，将分布式系统分隔为独立的几个部分，各个部分还能维持分布式系统的运作，这样就具有好的分区容错性。</span></p>
  <p data-lake-id="u4855fd6c" id="u4855fd6c"><span data-lake-id="u85658585" id="u85658585">​</span><br></p>
  <p data-lake-id="ufe688979" id="ufe688979"><span data-lake-id="ua6a59930" id="ua6a59930">简单点说，就是在网络中断，消息丢失的情况下，系统如果还能正常工作，就是有比较好的分区容错性。</span></p>
  <p data-lake-id="u422a7432" id="u422a7432" style="text-align: justify"><span data-lake-id="u622b4d1f" id="u622b4d1f" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <h2 data-lake-id="Kfzii" id="Kfzii" style="text-align: justify"><span data-lake-id="ud9c78860" id="ud9c78860" style="color: rgb(85, 85, 85)">CAP的证明</span></h2>
  <p data-lake-id="u4bd6dd47" id="u4bd6dd47"><br></p>
  <p data-lake-id="ubf927046" id="ubf927046" style="text-align: justify"><img src="https://cdn.nlark.com/yuque/0/2022/png/5378072/1666605119976-5be39022-c1e4-44a8-93a4-789d5d782486.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u1eff7ffc" id="u1eff7ffc" style="text-align: justify"><br></p>
  <p data-lake-id="ua96347af" id="ua96347af" style="text-align: justify"><span data-lake-id="uc4a5f668" id="uc4a5f668" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">如上图，是我们证明CAP的基本场景，网络中有两个节点N1和N2，可以简单的理解N1和N2分别是两台计算机，他们之间网络可以连通，N1中有一个应用程序A，和一个数据库V，N2也有一个应用程序B2和一个数据库V。现在，A和B是分布式系统的两个部分，V是分布式系统的数据存储的两个子数据库。</span></p>
  <p data-lake-id="u28bc5ff0" id="u28bc5ff0" style="text-align: justify"><span data-lake-id="u70372d3f" id="u70372d3f" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u0ca3aab1" id="u0ca3aab1" style="text-align: justify"><span data-lake-id="ubccc32ee" id="ubccc32ee" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">在满足一致性的时候，N1和N2中的数据是一样的，V0=V0。在满足可用性的时候，用户不管是请求N1或者N2，都会得到立即响应。在满足分区容错性的情况下，N1和N2有任何一方宕机，或者网络不通的时候，都不会影响N1和N2彼此之间的正常运作。</span></p>
  <p data-lake-id="u323461c3" id="u323461c3" style="text-align: justify"><span data-lake-id="u647a9f68" id="u647a9f68" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u285ad8f8" id="u285ad8f8" style="text-align: justify"><img src="https://cdn.nlark.com/yuque/0/2022/png/5378072/1666605119971-6cc6eb04-4b50-483e-913a-6a153f845b1b.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ue3a7703c" id="ue3a7703c" style="text-align: justify"><span data-lake-id="uc3842eaf" id="uc3842eaf" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">如上图，是分布式系统正常运转的流程，用户向N1机器请求数据更新，程序A更新数据库Vo为V1，分布式系统将数据进行同步操作M，将V1同步的N2中V0，使得N2中的数据V0也更新为V1，N2中的数据再响应N2的请求。</span></p>
  <p data-lake-id="u617fe6fc" id="u617fe6fc" style="text-align: justify"><span data-lake-id="u94e2ced3" id="u94e2ced3" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u21c4b3a1" id="u21c4b3a1" style="text-align: justify"><span data-lake-id="u236855a1" id="u236855a1" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">这里，可以定义N1和N2的数据库V之间的数据是否一样为一致性；外部对N1和N2的请求响应为可用性；N1和N2之间的网络环境为分区容错性。这是正常运作的场景，也是理想的场景，然而现实是残酷的，当错误发生的时候，一致性和可用性还有分区容错性，是否能同时满足，还是说要进行取舍呢？</span></p>
  <p data-lake-id="u6ab70a03" id="u6ab70a03" style="text-align: justify"><span data-lake-id="ub4ba6467" id="ub4ba6467" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="ue47029a2" id="ue47029a2" style="text-align: justify"><span data-lake-id="u296cdbca" id="u296cdbca" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">作为一个分布式系统，它和单机系统的最大区别，就在于网络，现在假设一种极端情况，N1和N2之间的网络断开了，我们要支持这种网络异常，相当于要满足分区容错性，能不能同时满足一致性和响应性呢？还是说要对他们进行取舍。</span></p>
  <p data-lake-id="u35140a09" id="u35140a09" style="text-align: justify"><img src="https://cdn.nlark.com/yuque/0/2022/png/5378072/1666605119967-32114fa6-5b72-4f08-9d1f-04994dae210f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u21c246a7" id="u21c246a7" style="text-align: justify"><span data-lake-id="u51189ff3" id="u51189ff3" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">假设在N1和N2之间网络断开的时候，有用户向N1发送数据更新请求，那N1中的数据V0将被更新为V1，由于网络是断开的，所以分布式系统同步操作M，所以N2中的数据依旧是V0；这个时候，有用户向N2发送数据读取请求，由于数据还没有进行同步，应用程序没办法立即给用户返回最新的数据V1，怎么办呢？</span></p>
  <p data-lake-id="uc38411c4" id="uc38411c4" style="text-align: justify"><span data-lake-id="u2f8fbc67" id="u2f8fbc67" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u55431bc8" id="u55431bc8" style="text-align: justify"><span data-lake-id="ucbc7981f" id="ucbc7981f" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">有二种选择，第一，牺牲数据一致性，保证可用性。响应旧的数据V0给用户；</span></p>
  <p data-lake-id="u1e68c838" id="u1e68c838" style="text-align: justify"><span data-lake-id="u61ee0472" id="u61ee0472" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="ua1475680" id="ua1475680" style="text-align: justify"><span data-lake-id="u2f652b21" id="u2f652b21" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">第二，牺牲可用性，保证数据一致性。阻塞等待，直到网络连接恢复，数据更新操作M完成之后，再给用户响应最新的数据V1。</span></p>
  <p data-lake-id="u2e4a0ec0" id="u2e4a0ec0" style="text-align: justify"><span data-lake-id="u96607a8f" id="u96607a8f" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u85e7ef64" id="u85e7ef64" style="text-align: justify"><span data-lake-id="u97d11ae0" id="u97d11ae0" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">这个过程，证明了要满足分区容错性的分布式系统，只能在一致性和可用性两者中，选择其中一个。</span></p>
  <h2 data-lake-id="RJSfE" id="RJSfE"><span data-lake-id="u4c250213" id="u4c250213" style="color: rgb(85, 85, 85)">CAP权衡</span></h2>
  <p data-lake-id="ub4dc9043" id="ub4dc9043"><br></p>
  <p data-lake-id="ubfb49e27" id="ubfb49e27" style="text-align: justify"><span data-lake-id="uc0757df2" id="uc0757df2" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">通过CAP理论及前面的证明，我们知道无法同时满足一致性、可用性和分区容错性这三个特性，那要舍弃哪个呢？</span></p>
  <p data-lake-id="u992a41ba" id="u992a41ba" style="text-align: justify"><span data-lake-id="u7add203b" id="u7add203b" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="ue4c254c6" id="ue4c254c6" style="text-align: justify"><span data-lake-id="u88d5d05e" id="u88d5d05e" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">我们分三种情况来阐述一下。</span></p>
  <h3 data-lake-id="W9Pmz" id="W9Pmz" style="text-align: justify"><span data-lake-id="u033d33d1" id="u033d33d1" style="color: rgb(85, 85, 85)">CA without P</span></h3>
  <p data-lake-id="u2f2e694a" id="u2f2e694a" style="text-align: justify"><span data-lake-id="uf1b84756" id="uf1b84756" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">这种情况在分布式系统中几乎是不存在的。首先在分布式环境下，网络分区是一个自然的事实。因为分区是必然的，所以如果舍弃P，意味着要舍弃分布式系统。那也就没有必要再讨论CAP理论了。这也是为什么在前面的CAP证明中，我们以系统满足P为前提论述了无法同时满足C和A。</span></p>
  <p data-lake-id="ue20003ca" id="ue20003ca" style="text-align: justify"><span data-lake-id="u04e9c49d" id="u04e9c49d" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u34ea1c86" id="u34ea1c86" style="text-align: justify"><span data-lake-id="ued1bb3d8" id="ued1bb3d8" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">比如我们熟知的关系型数据库，如My Sql和Oracle就是保证了可用性和数据一致性，但是他并不是个分布式系统。一旦关系型数据库要考虑主备同步、集群部署等就必须要把P也考虑进来。</span></p>
  <p data-lake-id="u304c5533" id="u304c5533" style="text-align: justify"><span data-lake-id="u127d13b6" id="u127d13b6" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u745ed098" id="u745ed098" style="text-align: justify"><span data-lake-id="u7ac5e6b6" id="u7ac5e6b6" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">其实，在CAP理论中。C，A，P三者并不是平等的，CAP之父在《Spanner，真时，CAP理论》一文中写到：</span></p>
  <p data-lake-id="u8de76b29" id="u8de76b29" style="text-align: justify"><span data-lake-id="u7c2fa7de" id="u7c2fa7de" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u6e71957e" id="u6e71957e" style="text-align: justify"><span data-lake-id="u6ec2cb05" id="u6ec2cb05" class="lake-fontsize-12" style="color: rgb(153, 153, 153)">如果说Spanner真有什么特别之处，那就是谷歌的广域网。Google通过建立私有网络以及强大的网络工程能力来保证P，在多年运营改进的基础上，在生产环境中可以最大程度的减少分区发生，从而实现高可用性。</span></p>
  <p data-lake-id="u4aebfb29" id="u4aebfb29" style="text-align: justify"><span data-lake-id="uf3142176" id="uf3142176" class="lake-fontsize-12" style="color: rgb(153, 153, 153)">​</span><br></p>
  <p data-lake-id="ucafe0759" id="ucafe0759" style="text-align: justify"><span data-lake-id="ua36cad6e" id="ua36cad6e" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">从Google的经验中可以得到的结论是，无法通过降低CA来提升P。要想提升系统的分区容错性，需要通过提升基础设施的稳定性来保障。</span></p>
  <p data-lake-id="u6f040d29" id="u6f040d29" style="text-align: justify"><span data-lake-id="uda3c376a" id="uda3c376a" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="ua76b722b" id="ua76b722b" style="text-align: justify"><span data-lake-id="ud3f7526a" id="ud3f7526a" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">所以，对于一个分布式系统来说。P是一个基本要求，CAP三者中，只能在CA两者之间做权衡，并且要想尽办法提升P。</span></p>
  <p data-lake-id="u6e4da2c2" id="u6e4da2c2" style="text-align: justify"><span data-lake-id="u3233ab34" id="u3233ab34" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <h3 data-lake-id="FLK3C" id="FLK3C" style="text-align: justify"><span data-lake-id="u0d5568dc" id="u0d5568dc" style="color: rgb(85, 85, 85)">CP without A</span></h3>
  <p data-lake-id="u84d51cf0" id="u84d51cf0"><br></p>
  <p data-lake-id="uf5d0b66b" id="uf5d0b66b" style="text-align: justify"><span data-lake-id="u21508e59" id="u21508e59" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">如果一个分布式系统不要求强的可用性，即容许系统停机或者长时间无响应的话，就可以在CAP三者中保障CP而舍弃A。</span></p>
  <p data-lake-id="u117d198e" id="u117d198e" style="text-align: justify"><span data-lake-id="u2c13f6c8" id="u2c13f6c8" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u0c4c1456" id="u0c4c1456" style="text-align: justify"><span data-lake-id="uc2896a5c" id="uc2896a5c" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">一个保证了CP而一个舍弃了A的分布式系统，一旦发生网络故障或者消息丢失等情况，就要牺牲用户的体验，等待所有数据全部一致了之后再让用户访问系统。</span></p>
  <p data-lake-id="ud5f10242" id="ud5f10242" style="text-align: justify"><span data-lake-id="ubc8e1de9" id="ubc8e1de9" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u12767ac4" id="u12767ac4" style="text-align: justify"><span data-lake-id="ue455b80e" id="ue455b80e" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">设计成CP的系统其实也不少，其中最典型的就是很多分布式数据库，他们都是设计成CP的。在发生极端情况时，优先保证数据的强一致性，代价就是舍弃系统的可用性。如HBase，还有分布式系统中常用的Zookeeper也是在CAP三者之中选择优先保证CP的。</span></p>
  <p data-lake-id="u89df657f" id="u89df657f" style="text-align: justify"><span data-lake-id="u11823aad" id="u11823aad" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u02e1c057" id="u02e1c057" style="text-align: justify"><span data-lake-id="u825268dc" id="u825268dc" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">无论是像HBase这种分布式存储系统，还是像Zookeeper这种分布式协调组件。数据的一致性是他们最最基本的要求。一个连数据一致性都保证不了的分布式存储要他有何用？</span></p>
  <p data-lake-id="u6224e8f5" id="u6224e8f5" style="text-align: justify"><br></p>
  <p data-lake-id="u6ad8c68c" id="u6ad8c68c" style="text-align: justify"><span data-lake-id="u2d660258" id="u2d660258" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">ZooKeeper是个CP（一致性+分区容错性）的，即任何时刻对ZooKeeper的访问请求能得到一致的数据结果，同时系统对网络分割具备容错性。但是它不能保证每次服务请求的可用性，也就是在极端环境下，ZooKeeper可能会丢弃一些请求，消费者程序需要重新请求才能获得结果。ZooKeeper是分布式协调服务，它的职责是保证数据在其管辖下的所有服务之间保持同步、一致。所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了。</span></p>
  <p data-lake-id="ud3e4c61e" id="ud3e4c61e" style="text-align: justify"><span data-lake-id="ue97e27e5" id="ue97e27e5" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <h3 data-lake-id="CmbAD" id="CmbAD" style="text-align: justify"><span data-lake-id="u27aa148e" id="u27aa148e" style="color: rgb(85, 85, 85)">AP wihtout C</span></h3>
  <p data-lake-id="ud6ead0bb" id="ud6ead0bb"><br></p>
  <p data-lake-id="ub2eda742" id="ub2eda742" style="text-align: justify"><span data-lake-id="uecd6274d" id="uecd6274d" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">要高可用并允许分区，则需放弃一致性。一旦网络问题发生，节点之间可能会失去联系。为了保证高可用，需要在用户访问时可以马上得到返回，则每个节点只能用本地数据提供服务，而这样会导致全局数据的不一致性。</span></p>
  <p data-lake-id="ucba16bcc" id="ucba16bcc" style="text-align: justify"><span data-lake-id="u44bdf990" id="u44bdf990" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="uc35de4e8" id="uc35de4e8" style="text-align: justify"><span data-lake-id="u2170f9b0" id="u2170f9b0" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">这种舍弃强一致性而保证系统的分区容错性和可用性的场景和案例非常多。前面我们介绍可用性的时候说到过，很多系统在可用性方面会做很多事情来保证系统的全年可用性可以达到N个9，所以，对于很多业务系统来说，比如淘宝的购物，12306的买票。都是在可用性和一致性之间舍弃了一致性而选择可用性。</span></p>
  <p data-lake-id="ue1aabc44" id="ue1aabc44" style="text-align: justify"><span data-lake-id="uc62e914a" id="uc62e914a" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="uc0f881d8" id="uc0f881d8" style="text-align: justify"><span data-lake-id="u7f696487" id="u7f696487" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">你在12306买票的时候肯定遇到过这种场景，当你购买的时候提示你是有票的（但是可能实际已经没票了），你也正常的去输入验证码，下单了。但是过了一会系统提示你下单失败，余票不足。这其实就是先在可用性方面保证系统可以正常的服务，然后在数据的一致性方面做了些牺牲，会影响一些用户体验，但是也不至于造成用户用户流失的严重阻塞。</span></p>
  <p data-lake-id="u26eee25f" id="u26eee25f" style="text-align: justify"><span data-lake-id="u2ebbf2da" id="u2ebbf2da" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u2b371cc2" id="u2b371cc2" style="text-align: justify"><span data-lake-id="uc31131bc" id="uc31131bc" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">但是，我们说很多网站牺牲了一致性，选择了可用性，这其实也不准确的。就比如上面的买票的例子，其实舍弃的只是强一致性。退而求其次保证了最终一致性。也就是说，虽然下单的瞬间，关于车票的库存可能存在数据不一致的情况，但是过了一段时间，还是要保证最终一致性的。</span></p>
  <p data-lake-id="uc8e6e38a" id="uc8e6e38a" style="text-align: justify"><span data-lake-id="u928a23f6" id="u928a23f6" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u99cbad45" id="u99cbad45" style="text-align: justify"><span data-lake-id="ua262799a" id="ua262799a" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">对于多数大型互联网应用的场景，主机众多、部署分散，而且现在的集群规模越来越大，所以节点故障、网络故障是常态，而且要保证服务可用性达到N个9，即保证P和A，舍弃C（退而求其次保证最终一致性）。</span></p>
  <p data-lake-id="ub0d2d7c6" id="ub0d2d7c6" style="text-align: justify"><span data-lake-id="u23dada3f" id="u23dada3f" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <h3 data-lake-id="Eavn1" id="Eavn1" style="text-align: justify"><span data-lake-id="u111abcf6" id="u111abcf6" style="color: rgb(85, 85, 85)">适合的才是最好的</span></h3>
  <p data-lake-id="ud9139ac7" id="ud9139ac7" style="text-align: justify"><span data-lake-id="u5e4fec03" id="u5e4fec03" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">上面介绍了如何CAP中权衡及取舍以及典型的案例。孰优孰略，没有定论，只能根据场景定夺，适合的才是最好的。</span></p>
  <p data-lake-id="u3e4593b8" id="u3e4593b8" style="text-align: justify"><span data-lake-id="ucb23adf5" id="ucb23adf5" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u951ad663" id="u951ad663" style="text-align: justify"><span data-lake-id="ub793667e" id="ub793667e" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">对于涉及到钱财这样不能有一丝让步的场景，C必须保证。网络发生故障宁可停止服务，这是保证CP，舍弃A。比如前几年支付宝光缆被挖断的事件，在网络出现故障的时候，支付宝就在可用性和数据一致性之间选择了数据一致性，用户感受到的是支付宝系统长时间宕机，但是其实背后是无数的工程师在恢复数据，保证数数据的一致性。</span></p>
  <p data-lake-id="u35b0bd01" id="u35b0bd01" style="text-align: justify"><span data-lake-id="u17a382ff" id="u17a382ff" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">​</span><br></p>
  <p data-lake-id="u23c77467" id="u23c77467" style="text-align: justify"><span data-lake-id="ub664e4c7" id="ub664e4c7" class="lake-fontsize-12" style="color: rgb(85, 85, 85)">对于其他场景，比较普遍的做法是选择可用性和分区容错性，舍弃强一致性，退而求其次使用最终一致性来保证数据的安全。</span></p>
  <p data-lake-id="ue5250fa6" id="ue5250fa6"><span data-lake-id="ufed9f726" id="ufed9f726"><br><br></span></p>
 </body>
</html>